--[[ Utility Functions ]]


---------------------------------------------------------------------------
-- Broadcast messages to screen
---------------------------------------------------------------------------
function BroadcastMessage( sMessage, fDuration,iPlayer )
	local centerMessage = {
		message = sMessage,
		duration = fDuration
	}
	if iPlayer then
		centerMessage["player_id"] = iPlayer
	end
	FireGameEvent( "show_center_message", centerMessage )
end

function doTeleport( caster,point_name )
	local entity = Entities:FindByName(nil, point_name);
	FindClearSpaceForUnit(caster,entity:GetAbsOrigin() , true)
	local id = caster:GetPlayerOwnerID()
	caster:Stop()
	PlayerResource:SetCameraTarget(id, caster)
	local selfGameMode = GameRules:GetGameModeEntity()
	selfGameMode:SetContextThink(DoUniqueString("cameraMove"),
	function (  ) PlayerResource:SetCameraTarget(id, nil) end,0.5)
end

function getNextBlock( curPoint,count )
	local toPoint = (curPoint+count-1) % MAX_LEN + 1
	return toPoint
end

function addAbilityToHero( hero,abilityName )
	if not hero:HasAbility(abilityName) then
		hero:AddAbility(abilityName)
		local ab = hero:FindAbilityByName(abilityName)
		if ab then
			ab:SetLevel(1)
		end
	end
end

function getItemInWeightlist( list,num,total )
	num = num or 1
	local ret = {}
	for i=1,num do
		local rd = RandomFloat(1,total)
		for k,v in pairs(list) do
			if v.from <= rd and v.to >= rd then
				table.insert(ret,k)
				break
			end
		end
	end
	return ret
end

function showWarn(message,player_id)
	local hPlayer
	local _t = type(player_id)
	if _t == 'number' then
		hPlayer = PlayerResource:GetPlayer(player_id)
	else
		hPlayer = player_id:GetPlayerOwner()
	end
	CustomGameEventManager:Send_ServerToPlayer(hPlayer,"S2C_ERROR_MSG",{text = message})
end

local function dump_value_(v)
    if type(v) == "string" then
        v = "\"" .. v .. "\""
    end
    return tostring(v)
end
function dump(value, desciption, nesting)
    if type(nesting) ~= "number" then nesting = 3 end

    local lookupTable = {}
    local result = {}

    local function dump_(value, desciption, indent, nest, keylen)
        desciption = desciption or "<var>"
        local spc = ""
        if type(keylen) == "number" then
            spc = string.rep(" ", keylen - string.len(dump_value_(desciption)))
        end
        if type(value) ~= "table" then
            result[#result +1 ] = string.format("%s%s%s = %s", indent, dump_value_(desciption), spc, dump_value_(value))
        elseif lookupTable[tostring(value)] then
            result[#result +1 ] = string.format("%s%s%s = *REF*", indent, dump_value_(desciption), spc)
        else
            lookupTable[tostring(value)] = true
            if nest > nesting then
                result[#result +1 ] = string.format("%s%s = *MAX NESTING*", indent, dump_value_(desciption))
            else
                result[#result +1 ] = string.format("%s%s = {", indent, dump_value_(desciption))
                local indent2 = indent.."    "
                local keys = {}
                local keylen = 0
                local values = {}
                for k, v in pairs(value) do
                    keys[#keys + 1] = k
                    local vk = dump_value_(k)
                    local vkl = string.len(vk)
                    if vkl > keylen then keylen = vkl end
                    values[k] = v
                end
                table.sort(keys, function(a, b)
                    if type(a) == "number" and type(b) == "number" then
                        return a < b
                    else
                        return tostring(a) < tostring(b)
                    end
                end)
                for i, k in ipairs(keys) do
                    dump_(values[k], k, indent2, nest + 1, keylen)
                end
                result[#result +1] = string.format("%s}", indent)
            end
        end
    end
    dump_(value, desciption, "- ", 1)

    for i, line in ipairs(result) do
        print(line)
    end
end

---------------------------------------------------------------------------
-- GetRandomElement
---------------------------------------------------------------------------
function GetRandomElement( table )
	local nRandomIndex = RandomInt( 1, #table )
    local randomElement = table[ nRandomIndex ]
    return randomElement
end

---------------------------------------------------------------------------
-- ShuffledList
---------------------------------------------------------------------------
function ShuffledList( orig_list )
	local list = shallowcopy( orig_list )
	local result = {}
	local count = #list
	for i = 1, count do
		local pick = RandomInt( 1, #list )
		result[ #result + 1 ] = list[ pick ]
		table.remove( list, pick )
	end
	return result
end

---------------------------------------------------------------------------
-- string.starts
---------------------------------------------------------------------------
function string.starts( string, start )
   return string.sub( string, 1, string.len( start ) ) == start
end

---------------------------------------------------------------------------
-- string.split
---------------------------------------------------------------------------
function string.split( str, sep )
    local sep, fields = sep or ":", {}
    local pattern = string.format("([^%s]+)", sep)
    str:gsub(pattern, function(c) fields[#fields+1] = c end)
    return fields
end

---------------------------------------------------------------------------
-- shallowcopy
---------------------------------------------------------------------------
function shallowcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in pairs(orig) do
            copy[orig_key] = orig_value
        end
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end

---------------------------------------------------------------------------
-- Table functions
---------------------------------------------------------------------------
function PrintTable( t, indent )
	--print( "PrintTable( t, indent ): " )
	if type(t) ~= "table" then return end

	for k,v in pairs( t ) do
		if type( v ) == "table" then
			if ( v ~= t ) then
				print( indent .. tostring( k ) .. ":\n" .. indent .. "{" )
				PrintTable( v, indent .. "  " )
				print( indent .. "}" )
			end
		else
		print( indent .. tostring( k ) .. ":" .. tostring(v) )
		end
	end
end

function TableFindKey( table, val )
	if table == nil then
		print( "nil" )
		return nil
	end

	for k, v in pairs( table ) do
		if v == val then
			return k
		end
	end
	return nil
end

function TableLength( t )
	local nCount = 0
	for _ in pairs( t ) do
		nCount = nCount + 1
	end
	return nCount
end

function tablefirstkey( t )
	for k, _ in pairs( t ) do
		return k
	end
	return nil
end

function tablehaselements( t )
	return tablefirstkey( t ) ~= nil
end

function ConvertToTime( value )
  	local value = tonumber( value )

	if value <= 0 then
		return "00:00:00";
	else
	    hours = string.format( "%02.f", math.floor( value / 3600 ) );
	    mins = string.format( "%02.f", math.floor( value / 60 - ( hours * 60 ) ) );
	    secs = string.format( "%02.f", math.floor( value - hours * 3600 - mins * 60 ) );
	    if math.floor( value / 3600 ) == 0 then
	    	return mins .. ":" .. secs
	    end
	    return hours .. ":" .. mins .. ":" .. secs
	end
end

function deepclone( object )
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for key, value in pairs(object) do
            new_table[_copy(key)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

function createTimerBar( total,func,str,args,start )
	local cur = start or 0
	local isStart = false
	if start or (cur == 0) then
		isStart = true
	else
		isStart = false
	end
	local ret = Timers:CreateTimer(function (  )
		if cur >= total then
			if func then
				func()
			end
			GameRules.last_round_timer = nil
			return nil
		else
			CustomGameEventManager:Send_ServerToAllClients("S2C_CHANGE_TIME",{cur=cur,total=total,str=str,args = args,isStart = isStart})
			cur = cur + 1
			GameRules.last_round_timer = cur
			return 1
		end
	end)
	return ret
end
--[[
	@param id 金币获得者
	@param gold 金币数量
	@param idfrom 金币来自的玩家
]]
function ModifyGoldLtx( id,gold,idfrom )
	if gold == 0 then
		return
	end

	local hero = PlayerResource:GetSelectedHeroEntity(id)
	local target
	if idfrom then
		target = PlayerResource:GetSelectedHeroEntity(idfrom)
	end
	_modifyGold(id,gold)
	
	--通知UI刷新  播放金币特效
	local infos = {{
		playerid = id,
		gold = _getGold(id),
	}}
	
	
	local partID = ParticleManager:CreateParticle("particles/econ/items/alchemist/alchemist_midas_knuckles/alch_hand_of_midas.vpcf",PATTACH_ABSORIGIN_FOLLOW,hero)
	ParticleManager:SetParticleControl(partID, 1, hero:GetAbsOrigin())
	if idfrom then
		_modifyGold(idfrom,-gold)
		--这个特效需要链接两个单位
		
		ParticleManager:SetParticleControl(partID, 0, target:GetAbsOrigin())
		PopupGoldCost(target,gold)
		table.insert(infos,{playerid = idfrom,gold=_getGold(idfrom)})
	else
		--单个金币特效
		ParticleManager:SetParticleControl(partID, 0, hero:GetAbsOrigin())
	end
	CustomGameEventManager:Send_ServerToAllClients("S2C_UPDATE_PLAYER_INFO",{infos=infos})
	EmitGlobalSound("General.CoinsBig")
	PopupGoldCost(hero,gold)
end

function _getGold( id )
	return GameRules.golds[id+1]
end

function _setGold( id,gold )
	GameRules.golds[id+1] = gold
end

function _modifyGold( id,gold )
	GameRules.golds[id+1] = GameRules.golds[id+1] + gold
end

function changeModelColor( cityid,color )
	local cityData = GameRules.blocks[cityid]
	local owner = cityData.owner
	local hero = PlayerResource:GetSelectedHeroEntity(owner)
	local pos = GetGroundPosition(cityData.partPos,hero)
	ParticleManager:DestroyParticle(cityData.partID,true)
	local partID = ParticleManager:CreateParticle("particles/items2_fx/owner_tp.vpcf", PATTACH_ABSORIGIN,hero )
	ParticleManager:SetParticleControlEnt(partID, 3, hero, PATTACH_ABSORIGIN, "follow_origin", pos, true)
	ParticleManager:SetParticleControl(partID,0,pos)
	ParticleManager:SetParticleControl(partID,4,Vector(1,0,0))
	ParticleManager:SetParticleControl(partID, 5, pos)
	ParticleManager:SetParticleControl(partID,6,color)
	cityData.partID = partID
end

function getIndexById( id )
	for i,v in ipairs(GameRules.playerlist) do
		if v == id then
			return i
		end
	end
end
--[[
	这里可以假设至少有一个玩家没有放弃，可以在放弃的操作中 直接对游戏进行终结
]]
function getNextIdx( idx )
	local record = {}
	while true do
		idx = idx + 1
		if idx > #GameRules.playerlist then
			idx = 1
		end
		--if GameRules.giveups[idx] then
			if record[idx] then
				return false
			else
				record[idx] = true
			end
		--else
			return idx
		--end
	end
end

function unregisterTimer( timer )
	if timer then
		Timers:RemoveTimer(timer)
	end
end
